using System;
using System.IO;


namespace sqlcmd
{
   /// <summary>
   /// Parameters is a struct to hold and verify parameters passed to the program.
   /// </summary>
   internal class Parameters
   {
      private string m_args;
      private string m_connectString;
		private string m_script;
		public DBType DBType { get; private set; }
		public string Script
		{
			get { return m_script; }
		}
	
      public string ConnectString
      {
         get { return m_connectString; }
         set { m_connectString = value; }
      }

      private string m_connectClass;
      public string ConnectClass
      {
         get { return m_connectClass; }
         set { m_connectClass = value; }
      }

      public Parameters (string[] args, Settings settings)
      {
         if (args.Length<1)
         {
            throw new ParameterException("No parameters");
         }
         m_args += args[0] + " ";
         DBType = settings.GetDBType( args[0] );
			if (DBType == null)
         {
            throw new ParameterException(string.Format("DBType {0} not found in settings.xml", args[0] ));
         }
			m_connectString = DBType.Properties.ConnectionString;
			m_connectClass = DBType.Properties.ConnectionClass;
			int noConnectParams = 0;
			for (int idx = m_connectString.IndexOf("{", 0); idx != -1; idx = m_connectString.IndexOf("{", ++idx))
			{
				noConnectParams++;
			}
			int noTST = 0;
			for (int idx = m_connectString.IndexOf("}", 0); idx != -1; idx = m_connectString.IndexOf("}", ++idx))
			{
				noTST++;
			}
			if (noTST != noConnectParams)
			{
				throw new ParameterException("Bad format of <ConnectionString> in settings.xml");
			}

         for (int parameterNo = 1; parameterNo < args.Length; parameterNo++ )
         {
				if (args[parameterNo] == "-F")
				{
					m_script = GetParameter(args, ++parameterNo, "Scriptfile");
				}
				else if(parameterNo-1<noConnectParams)
				{
					m_args += args[parameterNo] + " ";
					string thisParam = string.Format("{0}{1}{2}", "{", parameterNo - 1, "}");
					if (m_connectString.IndexOf(thisParam) < 0)
					{
						throw new ParameterException(string.Format("Wrong number of parameters. can't find value for parameter {{0}}}\n\rfor ConnectionString {1}", parameterNo - 1, DBType.Properties.ConnectionString));
					}
					m_connectString = m_connectString.Replace(thisParam, args[parameterNo]);
				}
         }
			if (!string.IsNullOrEmpty(m_script) && !File.Exists(m_script))
			{
				throw new ParameterException(string.Format("Script file ({0}) does not exist.", m_script));
			}
      }

      public ParameterException CreateParameterException( string msg )
      {
         string usage = @"
usage:
sqlcmd DBType ConnectStringParameter0 ConnectStringParameter1 ConnectStringParameter2
   Where ConnectStringParameters is found in settings.xml
";
         return new ParameterException( "Wrong parameters. \r\n" + m_args + "\r\n" + msg + usage ); 
      }

      private string GetParameter( string[] args, int parameterNo, string msg )
      {
         try
         {
            return args[parameterNo];
         }
         catch
         {
            throw CreateParameterException( "no valid " + msg + " parameter found" );
         }
         
      }
   }

   internal class ParameterException : ApplicationException
   {
      public ParameterException(string msg) : base(msg){}
   }
}
